<?php
namespace App\Libs\Pay;

use App\Libs\Views\Exception;
use Phalcon\Config\Adapter\Ini as ConfigIni;
use App\Libs\Base\Config;
//use App\Libs\Pay\Event;
require __DIR__ . '/Alipay/AopSdk.php';

class PayLibs extends Event
{
    protected $closureMap;
    static $aopClientObj;
    static $alipayConfig;
    public function attach($event,\Closure $closure){
        if(!isset($this->closureMap[$event])){
            $this->closureMap[$event] = $closure;
        }else{
            throw new \Exception('重复注册事件');
        }
    }

    public function detach($event){
        if(isset($this->closureMap[$event])) {
            unset($this->closureMap[$event]);
        }
    }

    public function trigger($event,$args){
        return call_user_func_array( $this->closureMap[$event] , $args);
    }
    /**
     * PayLibs constructor.
     * @param bool $check 是否是验证
     */
    public function __construct($check = false)
    {
        self::$aopClientObj = new \AopClient();
        //支付参数
        self::$alipayConfig = Config::instance()->pay['alipay'];
        if (!$check) {
            self::$aopClientObj->appId = self::$alipayConfig['appId'];
            self::$aopClientObj->rsaPrivateKey = self::$alipayConfig['rsaPrivateKey'];
            self::$aopClientObj->signType = self::$alipayConfig['signType'];
        }
        self::$aopClientObj->alipayrsaPublicKey = self::$alipayConfig['alipayrsaPublicKey'];
    }


    /**
     * @param $goodsInfo   商品描述信息;subject，out_trade_no,total_amount,product_code(必须)
     * @return array
     */
    public static function getAlipayAppStr($goodsInfo)
    {
        $aopClient = new self();
        $createReq = new \AlipayTradeAppPayRequest();
        $createReq->setNotifyUrl(self::$alipayConfig['notify_url']);
        $createReq->setBizContent(json_encode($goodsInfo));
        $queryString = $aopClient::$aopClientObj->sdkExecute($createReq);
        return [
            'alipayStr' => $queryString
        ];
    }

    public static function getAlipayH5Str($goodsInfo){
        $aopClient = new self();
        $createReq = new \AlipayTradeWapPayRequest();
        $createReq->setNotifyUrl(self::$alipayConfig['notify_url']);
        $createReq->setBizContent(json_encode($goodsInfo));
        $jumpUrl = $aopClient::$aopClientObj->pageExecute($createReq,'GET');
       return $jumpUrl;
    }

    public function checkResult($post)
    {

        $flag = self::$aopClientObj->rsaCheckV1($post, NULL, self::$alipayConfig['signType']);  //验证签名
        if ($flag) {
            //验证支付逻辑
            $data['out_trade_no'] = $post['out_trade_no'];
            $data['alipay_trade_no']= $post['trade_no'];
            $data['alipay_pay_time']= $post['gmt_payment'];
            //交易状态：字符串
            $data['trade_status'] = $post['trade_status'];
            //交易额
            $data['total_amount'] = $post['total_amount'];
            $data['pass_params'] = json_decode(urldecode($post['passback_params']));
            $appId = $post['app_id'];
            //1 ：验证appid
            if (self::$alipayConfig['appId'] != $appId) {
                echo 'failure';
                die;
            }
            //2 ： 验证seller_email
            if (self::$alipayConfig['seller_email'] != $post['seller_email']) {
                echo 'failure';
                die;
            }
            //3 : 验证是否有此订单号码,分为：chargeVIP，充值会员;purchaseLessions:购买课程;
            if ($data['pass_params']->type == 'chargeVIP') {
                //验证充值会员的订单；验证金额对不对;
                if(isset($this->closureMap['chargeVIPCheck'])){
                    $res = $this->trigger('chargeVIPCheck',$data);
                    if(!$res){
                        echo 'failure';
                        die;
                    }
                }else{
                    throw new \Exception('事件(chargeVIPCheck)未注册');
                }
            } elseif ($data['pass_params']->type == 'purchaseLessions') {
                //验证购买订单是否存在，金额是否正确;
                if(isset($this->closureMap['purchaseLessionsCheck'])){
                    $res = $this->trigger('purchaseLessionsCheck',$data);
                    if(!$res){
                        echo 'failure';
                        die;
                    }
                }else{
                    throw new \Exception('事件(purchaseLessionsCheck)未注册');
                }
            }
            //官方文档4步验证完成，所有数据校验已经完成
            if ($data['trade_status'] == 'TRADE_SUCCESS' || $data['trade_status'] == 'TRADE_FINISHED') {
                if ($data['pass_params']->type == 'chargeVIP') {
                    /**
                     * 根据订单状态检测重复通知；
                     * 保存返回信息
                     */
                    if(isset($this->closureMap['chargeVIPResult'])){
                        $res = $this->trigger('chargeVIPResult',$data);
                        if(!$res){

                            echo 'failure';
                            die;
                        }
                    }else{
                        throw new \Exception('事件(chargeVIPResult)未注册');
                    }

                } elseif ($data['pass_params']->type == 'purchaseLessions') {
                    /**
                     * 确定订单状态；防止重复通知；
                     * 保存通知数据；
                     * 修改订单状态；
                     * 增加销量；
                     */
                    if(isset($this->closureMap['purchaseLessionsResult'])){
                        $res = $this->trigger('purchaseLessionsResult',$data);
                        if(!$res){

                            echo 'failure';
                            die;
                        }
                    }else{
                        throw new \Exception('事件(purchaseLessionsResult)未注册');
                    }
                }
            } elseif ($data['trade_status'] == 'TRADE_CLOSED') {
                //交易关闭未做
                echo 'success';
                die;
            }
        } else {
            //验签失败
            echo 'failure';
            die;
        }
    }


    /**
     * @param array $refundInfo 数组：至少包含订单号和退款金额:
     *                      out_trade_no(本系统订单号),
     *                      refund_amount（退款金额）
     *                      trade_no（支付宝交易号）
     * @return array|\SimpleXMLElement[]
     */
    public static function alipayRefund($refundInfo = [])
    {
        $refundRequest = new \AlipayTradeRefundRequest();
        $refundRequest->setBizContent(json_encode($refundInfo));
        $payLibs = new self();
        $result = $payLibs::$aopClientObj->execute($refundRequest);
        $responseNode = str_replace(".", "_", $refundRequest->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if (!empty($resultCode) && $resultCode == 10000) {
            //成功
            return $result->$responseNode;
        } else {
            //失败
            if (isset($result->$responseNode->sub_msg)) {
                $returnMsg = $result->$responseNode->sub_msg;
            } else {
                $returnMsg = $result->$responseNode->msg;
            }
            return ['status' => 0, 'msg' => $returnMsg];
        }

    }



    public static function logNotifyInfo($payType,$data,$logFileName){

        $msgbefore ="
########################################################
系统收到一笔{$payType}订单通知，详细信息如下：
";
        $afterMsg='
########################################################
';
        $msg = $msgbefore . var_export($data, true).$afterMsg;
        Logger::info($logFileName, $msg);
    }



    public static function log($type,$paytype,$errorMsg,$data,$logFileName){
        $msgbefore ="
########################################################
类型：{$type}                支付方式：{$paytype}     
错误信息：{$errorMsg}  
";
        $afterMsg='
########################################################
';
        $msg = $msgbefore . var_export($data, true).$afterMsg;
        Logger::info($logFileName, $msg);
    }





}

